1.問卷鑲嵌介面的設計構想
2.程式實作
3.Dart語言學習: @override
注釋
4.介面成果
Score_Page.dart
(1)將問卷的七個題目,和每個題目的選項,以上下滑動視窗顯示在介面上。
(2)針對每題的回答,使用Map(Dictionary)的Key和Value,將每題使用者勾選的選項儲存在變數中,讓程式進行總分計算,並按照總分級距,回傳對應的疾病嚴重程度到App介面。
針對以上,在該Dart檔案,程式架構如下圖:
(1)class Question{}
將問卷的七個題目,和每個題目的選項,以上下滑動視窗顯示在介面上
自定義 Dart 類別,代表一個問題的數據結構
// 定義了一個 Dart 類別 Question,用於封裝表示問題的數據
// 包含每個問題的內容(問題內容、選項和鍵值),然後在ScorePageState中創建了一個questions列表,其中包含所有的問題
// 這種設計可以方便地將問題的相關數據組織起來,將多個 Question 對象組成一個問題集合,用於測驗或問卷等應用場景
class Question {
final String question; // `final`代表不可變的屬性,代表問題的文字描述
final List<String> options; // 代表問題的選項列表,選項以字符串的形式存儲在列表中
final String key; // 代表問題的唯一鍵值,將用於識別和查找特定的問題
// 是該類別的構造函式,接收問題、選項和鍵值作為必要的參數
// 通過這個構造函式,可以創建一個 Question 對象,並初始化其中的屬性
Question({required this.question, required this.options, required this.key});
}
(2)Widget buildQuestion()
: 用於建立單一個問題的 UI
這段程式碼是用於建立單個問題的 UI 的方法,並處理用戶的選擇。以下是對它的詳細說明:
buildQuestion
方法是一個小部件,接受以下參數:
question
:問題的文字描述。options
:問題的選項列表。onOptionSelected
:當用戶選擇選項時的回調函式。currentQuestion
:當前問題的唯一鍵值,用於識別問題。Column
小部件用於垂直排列問題文本和選項。
問題文本使用 Text
小部件顯示,並設置字體樣式。
使用 options.map
方法將每個選項映射為 ListTile
小部件。
ListTile
包括問題選項的文本 (Text
) 和選項的 Radio
按鈕。Radio
按鈕用於表示選項,value
是選項的分數,groupValue
是該問題的當前選擇分數。onChanged
回調函式會被觸發,將選擇的分數更新到 scores
映射中,並調用 onOptionSelected
回調函式。這個方法的主要作用是顯示單個問題,讓用戶選擇選項,並根據用戶的選擇更新 scores
映射,這個映射將用於計算症狀總分。這種設計允許用戶回答多個問題,並在 UI 上即時反映他們的選擇。
// buildQuestion() 方法用於構建單一個問題的 UI,包括問題文本和選項列表,用戶可以通過點擊選項來選擇分數
Widget buildQuestion(String question, List<String> options, Function(int) onOptionSelected, String currentQuestion) { // 選項都列出來,讓使用者點選
return Column(
children: [
Text(question, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
...options.map((option) {
int optionScore = options.indexOf(option); // 第一個選項為0分, 若 options.indexOf(option) + 1: 第一個選項為1分
return ListTile(
title: Text(option), // 顯示選項文字
leading: Radio(
value: optionScore, // 選項的分數值
groupValue: scores[currentQuestion], // 當前問題的用戶選擇分數
onChanged: (int? value) {
if (value != null) {
setState(() {
scores[currentQuestion] = value; // 更新問題的用戶選擇分數
});
onOptionSelected(value); // 調用回調函式以處理選擇
}
},
),
);
}).toList(),
],
);
}
(3)Widget build()
: 用於構建整個分數頁面的 UI,包括: 問題列表、症狀總分顯示、儲存按鈕和查看分數歷史圖表build
方法中,它是整個分數頁面的 UI 構建部分,處理以下主要內容:
主題和外觀設定
Theme
小部件設置應用程式的主題風格,包括主要顏色和 AppBar 的背景色。Scaffold 和 AppBar**
Scaffold
小部件構建整個頁面的基本結構,包括背景色。AppBar
,顯示應用程式的標題為 "國際攝護腺症狀評分表: IPSS"。問題列表
ListView.builder
構建問題列表,其中每個問題都是通過 buildQuestion
方法構建的。questions
列表,並根據索引動態生成問題 UI。症狀總分顯示
Row
小部件,將症狀總分和症狀嚴重程度顯示在界面上。scores
映射中的值計算,然後顯示在界面上。與之前提到的 buildQuestion
方法不同,這部分程式碼是分數頁面的整體結構,包括整個界面的佈局、主題風格和按鈕處理。這個 build
方法是 Flutter 小部件生命週期中的一部分,當小部件需要構建其 UI 時會被調用。
@override
// build() 方法用於構建整個分數頁面的 UI,包括: 問題列表、症狀總分顯示、儲存按鈕和查看分數歷史圖表按鈕
// '評分頁面', 症狀總分, 儲存, 查看分數歷史圖表
Widget build(BuildContext context) {
return Theme(
data: ThemeData(
// primaryColor: const Color(0xFFC2185B), // 使用自定義顏色作為主要顏色
primarySwatch: Colors.pink, // 主題色彩
appBarTheme: const AppBarTheme(backgroundColor: Color(0xFFC2185B)) // 使用自定義顏色作為 AppBar 的背景色
),
child: Scaffold(
backgroundColor: backgroundColor, // 背景色
appBar: AppBar(title: const Text('國際攝護腺症狀評分表: IPSS')),
body: Column( // 將問題由上到下垂直排列
children: [
Expanded(
// 使用 ListView.builder 構建問題列表,每個問題都是通過 buildQuestion() 方法構建的
child: ListView.builder(
itemCount: questions.length,
itemBuilder: (context, index) {
var question = questions[index];
return buildQuestion(
question.question, // 問題文本
question.options, // 選項列表
// 使用 setState 方法來處理問題的選擇,同時更新症狀總分和背景顏色
(int score) => setState(() => scores[question.key] = score),
question.key,
);
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
// 顯示症狀總分
'症狀總分: ${scores.values.reduce((a, b) => a + b)}',
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
// 顯示症狀嚴重程度
'症狀嚴重程度: ${scores.values.reduce((a, b) => a + b) <= 7 ? '輕度' : (scores.values.reduce((a, b) => a + b) <= 19 ? '中度' : '重度')}',
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
],
),
],
),
),
);
}
@override
注釋(1)@override
注釋
@override
Widget build(BuildContext context){}
@override
:這是 Dart 語言提供的一個注釋,用來表示接下來的方法將覆蓋(重寫)父類別中具有相同名稱的方法。這個注釋通常用在子類別中,當你想要重寫父類別中已經存在的方法時。
在上述代碼中,@override
注釋用在 build
方法上,這是一個常見的做法,因為 build
方法是 Flutter 中的一個核心方法,用於構建小部件的 UI。
Widget build(BuildContext context)
:這是一個方法的定義,它在 State
子類別中覆蓋了父類別 StatefulWidget
的 build
方法。在 Flutter 中,build
方法是用於構建小部件的 UI 表示的地方。
BuildContext context
:這是 build
方法的參數,它提供了上下文信息,允許小部件訪問 Flutter 應用程式的環境和配置。它是一個重要的參數,通常需要在構建 UI 時使用。總結,@override
注釋告訴編譯器,這個方法將覆蓋父類別的方法,並且該方法用於構建小部件的 UI。當 Flutter 需要重新渲染小部件時,它將調用這個方法來生成新的 UI 表示。
你所有的努力,不該是為了讓他人佩服,而是讓自己真心以自己為傲
All your efforts should be aimed not at earning admiration from others, but at genuinely making yourself proud.
今天享受了一杯熱可可,工作進度報告也順利~晚上吃了美味又健康的晚餐,平淡的充實的一天,早早睡去明天繼續!